/* -+- file  ./kf2/GUI/VCard.cs -+- */
/*
 * kf2 jabber client
 * ~~~~~~~~~~~~~~~~~
 *
 * Copyright (C) 2006-2007 Przemysław Sitek
 * 				<przemyslaw.sitek at wp.pl> 
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

using System;
using Habazie.kf2.Core;
using Habazie.kf2.Net;
using Habazie.kf2.Roster;

namespace Habazie.kf2.GUI
{
	///<summary>
	///	Attribute that binds Widget to a named field in VCard
	///</summary>
	internal class VCardField : Attribute
	{
		public string Name;
		public VCardField (string name)
		{
			Name = name;
		}
	}
	
	
	///<summary>
	/// Contact information window
	///</summary>
	public class VCard : Gtk.Window
	{
		private Account m_Account;
		private Item m_Item = null;
		private string m_Resource = null;
		
		protected Gtk.Label m_JabberID;
		protected Gtk.Entry m_Nickname;
		protected Gtk.Label m_Subscription;

		[VCardField ("ROLE") ]		
		protected Gtk.Entry m_Role;
		
		[VCardField ("TITLE") ]
		protected Gtk.Entry m_Position;

		[VCardField ("ORG/ORGUNIT")]
		protected Gtk.Entry m_OrgUnit;

		[VCardField ("ORG/ORGNAME")]
		protected Gtk.Entry m_OrgName;
		
		[VCardField ("ADR/COUNTRY") ]
		protected Gtk.Entry m_Country;
		
		[VCardField ("ADR/PCODE") ]
		protected Gtk.Entry m_Postal;
		
		[VCardField ("ADR/REGION") ]
		protected Gtk.Entry m_State;
		
		[VCardField ("ADR/LOCALITY") ]
		protected Gtk.Entry m_City;
		
		[VCardField ("ADR/EXTADD") ]
		protected Gtk.Entry m_Street2;
		
		[VCardField ("ADR/STREET") ]
		protected Gtk.Entry m_Street;
		
		[VCardField ("TEL/VOICE") ]
		protected Gtk.Entry m_Phone;
		
		[VCardField ("URL") ]
		protected Gtk.Entry m_Homepage;
		
		[VCardField ("EMAIL") ]
		protected Gtk.Entry m_Email;
		
		[VCardField ("BDAY") ]
		protected Gtk.Entry m_Birthdate;
		
		[VCardField ("NICKNAME") ]
		protected Gtk.Entry m_Nick;
		
		[VCardField ("FN") ]
		protected Gtk.Entry m_RealName;
		
		protected Gtk.TextView m_About;
		protected Gtk.TextView m_Resources;
		protected Gtk.Image m_Photo;
		protected Gtk.Button m_AvatarLoad;
		protected Gtk.HButtonBox hbuttonbox2;

		
		public VCard(Account acc) : 
				base("")
		{
			m_Account = acc;
			Stetic.Gui.Build(this, typeof(Habazie.kf2.GUI.VCard));
			hbuttonbox2.Layout = Gtk.ButtonBoxStyle.Spread;
			hbuttonbox2.SetChildSize (32, 32);
			hbuttonbox2.QueueResize ();
		}
		
		
		///<summary>
		/// Get/set roster item displayed in this vcard
		///</summary>
		public Habazie.kf2.Roster.Item Item {
			get {
				return m_Item;
			}
			set {
				m_Item = value;
				if (m_Item != null) {
					m_JabberID.Text = m_Item.JabberID.Bare;
					m_Nickname.Text = m_Item.Name;
					m_Subscription.Text = m_Item.Sub.ToString ();
					if (m_Item.VCard != null)
						DisplayVCard (m_Item.VCard);
					DisplayResources ();
					Editable = false;
				}
			}
		}
		
		
		///<summary>
		/// Get/set whether user can modify contents of VCard
		///</summary>
		public bool Editable {
			get { return false; }
			set {
				bool editable = value;
				System.Reflection.FieldInfo [] fields = this.GetType ().GetFields(((System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic) | System.Reflection.BindingFlags.Instance));
				foreach (System.Reflection.FieldInfo field in fields) {
					try {
						VCardField f = (VCardField) System.Attribute.GetCustomAttribute (field, typeof (VCardField));
						Gtk.Entry widget = (Gtk.Entry) field.GetValue (this);
						
						widget.IsEditable = editable;
					} catch (Exception) {
		//				Util.ReportException (e);
					}
				}
			}
		}
		
		
		///<summary>
		/// Fetch VCard from server
		///</summary>
		public void Retrieve ()
		{
			m_Item.UpdateVCard ();
			m_Item.InformationChanged += ItemInfoUpdated;
//			try {
//				jabber.JID to;
//				if (m_Item != null)
//					to = m_Item.JabberID.Bare;
//				else
//					return;
//				
//				jabber.protocol.iq.VCardIQ iq = new jabber.protocol.iq.VCardIQ (m_Account.Document);
//				iq.To = to;
//				iq.Type = jabber.protocol.client.IQType.get;
//				m_Account.Tracker.BeginIQ (iq, Retrieved, null);
//			} catch (Exception e) {
//					System.Console.Error.WriteLine ("Exception: {0}@{1}", e.Message, e.StackTrace);
//			}
		}
		
		protected virtual void ItemInfoUpdated (object o, EventArgs a)
		{
			m_Item.InformationChanged -= ItemInfoUpdated;
			DisplayVCard (m_Item.VCard);
		}
		
		///<summary>
		///	Received vcard response
		///</summary>
		protected virtual void Retrieved (object sender, jabber.protocol.client.IQ iq, object data)
		{
//			jabber.protocol.iq.VCard vcard = null;
//			try {
//				vcard = (jabber.protocol.iq.VCard) iq["vCard"];
//			} catch (Exception e) {
//				Util.ReportException (e);
//			}
//			
//			if (vcard != null) {
//				Gtk.Application.Invoke (delegate {
//					DisplayVCard (vcard);
//				});
//			}
		}
				

		///<summary>
		///	Display a VCard
		///</summary>
		protected virtual void DisplayVCard (jabber.protocol.iq.VCard vcard)
		{
			Util.Debug ("GUI", "Got VCard response");
			
			/* Fill in entries */
			System.Reflection.FieldInfo [] fields = this.GetType ().GetFields(((System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic) | System.Reflection.BindingFlags.Instance));
			foreach (System.Reflection.FieldInfo field in fields) {
				try {
					VCardField f = (VCardField) System.Attribute.GetCustomAttribute (field, typeof (VCardField));
					Gtk.Entry entry = (Gtk.Entry) field.GetValue (this);
//					Util.Debug ("GUI", "Field {0} bound to {1}", field.Name, f.Name);
					
					// FIXME: Use XPath
					string [] items = f.Name.Split ('/');
					System.Xml.XmlElement el = vcard;
					foreach (string part in items) {
						el = el[part];
					}
					
					entry.Text = el.InnerText;
				} catch (Exception) {
				//	System.Console.Error.WriteLine ("Exception: {0} @ {1}", e.Message, e.StackTrace);
				}
			}
			
			/* Fill in "About" page and avatar */
			try {
				m_About.Buffer.Text = vcard["DESC"].InnerText;
				System.Xml.XmlElement el = vcard["PHOTO"];
				DisplayPhoto (el["BINVAL"].InnerText);
			} catch (Exception) {
			}
		}
		
		
		///<summary>
		///	Display avatar contained in VCard
		///</summary>
		///<param name="text">Base64 encoded image data</param>
		private void DisplayPhoto (string text)
		{
			byte [] data = System.Convert.FromBase64String (text);
			Gdk.Pixbuf loader = new Gdk.Pixbuf (data);
			m_Photo.Pixbuf = loader;
			m_Photo.Parent.Show ();
		}
		
		///<summary>
		///	Fill in "Resources" page
		///</summary>
		private void DisplayResources ()
		{
			if (m_Item == null)
				return;
				
			Gtk.TextBuffer buffer = m_Resources.Buffer;
			buffer.Clear ();
			foreach (Resource r in m_Item.Resources) {
				string s = String.Format ("{0} ({1})\n{2}: {3}\n\n",
					r.Name, r.Priority, r.Show, r.Status);
				buffer.InsertAtCursor (s);
			}
		}
		
		#region Event handlers


		///<summary>
		///	"Close" button was clicked
		///</summary>
		protected virtual void OnCloseClicked(object sender, System.EventArgs e)
		{
			Destroy ();
		}

		protected virtual void OnMChangeNicknameClicked(object sender, System.EventArgs e)
		{
		}

		protected virtual void OnMAvatarRemoveClicked(object sender, System.EventArgs e)
		{
		}

		protected virtual void OnMAvatarLoadClicked(object sender, System.EventArgs e)
		{
		}

		protected virtual void OnRefreshClicked(object sender, System.EventArgs e)
		{
			Retrieve ();
		}
		
		#endregion
	}
}
